package gxwl.common.page;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.annotation.JsonView;
import gxwl.common.model.Views;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 分页响应对象
 * @author jiangwh
 */
@Getter @Setter
@ToString
@Accessors(chain = true)
public class PageList<T> {

    @Schema(title = "分页数据列表")
    @JsonView({Views.Select.class})
    private List<T> rows = Collections.emptyList();

    @Schema(title = "当前页码")
    @JsonView({Views.Select.class})
    private Long pageNumber;

    @Schema(title = "每页条数")
    @JsonView({Views.Select.class})
    private Long pageSize;

    @Schema(title = "总数")
    @JsonView({Views.Select.class})
    private Long total;

    @Schema(title = "总页数")
    @JsonView({Views.Select.class})
    private Long totalPage;

    /**
     * 返回空对象
     * @param iPage 数据库分页对象
     * @return 分页对象
     * @param <D> 数据库分页数据类型
     * @param <T> 分页数据类型
     */
    public static <D, T> PageList<T> empty(IPage<D> iPage) {
        iPage.setTotal(0);
        iPage.setPages(0);
        return of(iPage, ListUtil.empty());
    }

    /**
     * 获取分页对象，自定义数据（不用数据库分页对象中的数据）
     * @param iPage 数据库分页对象
     * @param records 分页数据
     * @return 分页对象
     * @param <D> 数据库分页数据类型
     * @param <T> 分页数据类型
     */
    public static <D, T> PageList<T> of(IPage<D> iPage, List<T> records) {
        return new PageList<T>()
                .setPageNumber(iPage.getCurrent())
                .setPageSize(iPage.getSize())
                .setTotal(iPage.getTotal())
                .setTotalPage(iPage.getPages())
                .setRows(records);
    }

    /**
     * 获取分页对象，自定义转换规则（转换数据库分页对象中的数据）
     * @param iPage 数据库分页对象
     * @param mapper 分页数据转换规则（入参为row，代表一条数据库分页对象中的数据）
     * @return 分页对象
     * @param <D> 数据库分页数据类型
     * @param <T> 分页数据类型
     */
    public static <D, T> PageList<T> of(IPage<D> iPage, Function<? super D, ? extends T> mapper) {
        return of(
                iPage,
                iPage.getRecords().stream()
                        .map(mapper)
                        .collect(Collectors.toList()));
    }

    /**
     * 获取分页对象，全量bean拷贝（直接将数据库分页对象中的数据转换）
     * @param iPage 数据库分页对象
     * @param clazz 转换后的class
     * @return 分页对象
     * @param <D> 数据库分页数据类型
     * @param <T> 分页数据类型
     */
    public static <D, T> PageList<T> of(IPage<D> iPage, Class<T> clazz) {
        return of(iPage, row -> BeanUtil.copyProperties(row, clazz));
    }

    /**
     * 获取分页对象，对象没有发生变化时
     * @param iPage 数据库分页对象
     * @return 分页对象
     * @param <T> 分页数据类型
     */
    public static <T> PageList<T> of(IPage<T> iPage) {
        return of(iPage, iPage.getRecords());
    }

}